package cn.cuilan.service;

import cn.cuilan.enums.VerifyCodeType;
import com.yunpian.sdk.YunpianException;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.io.IOException;
import java.util.Random;

/**
 * 短信验证码服务
 *
 * @author zhangyue
 */
@Service
public class VerifyCodeService {

    private static Logger logger = Logger.getLogger(VerifyCodeService.class);

    private StringRedisTemplate stringRedisTemplate;

    private SMSVerifyCodeService smsVerifyCodeService;
    //生成随机数是使用以下Random对象进行生成
    private static final Random RANDOM = new Random();

    @Autowired
    public VerifyCodeService(StringRedisTemplate stringRedisTemplate,
                             SMSVerifyCodeService smsVerifyCodeService) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.smsVerifyCodeService = smsVerifyCodeService;
    }

    /**
     * 获取手机号，发送验证码
     *
     * @param phoneNumber
     * @param verifyCodeType
     */
    public void getVerifyCode(String phoneNumber, VerifyCodeType verifyCodeType) {
        Assert.notNull(verifyCodeType, "短信验证码类型不可为空");
        // 提供了对key的“bound”(绑定)便捷化操作API，可以通过bound封装指定的key，然后进行一系列的操作而无须“显式”的再次指定Key，
        Assert.isTrue(stringRedisTemplate.boundValueOps(VerifyCodeType.VERIFY_COUNT + phoneNumber)
                .get() == null, "未满一分钟，不能重复发送！");
        String code = String.valueOf(RANDOM.nextInt(1000000));
        stringRedisTemplate.boundListOps(verifyCodeType + phoneNumber).leftPush(code);
        try {
            smsVerifyCodeService.sendSms(phoneNumber, code);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (YunpianException e) {
            e.printStackTrace();
        }
    }

    /**
     * 校验
     *
     * @param phoneNumber
     * @param code
     * @param verifyCodeType
     */
    public void detectVerifyCode(String phoneNumber, String code, VerifyCodeType verifyCodeType) {
        Assert.notNull(verifyCodeType, "短信验证码不可为空");
        Assert.isTrue(stringRedisTemplate.boundListOps(verifyCodeType + phoneNumber)
                .index(0L) != null, "请先获取验证码");
        Assert.isTrue(stringRedisTemplate.boundListOps(verifyCodeType + phoneNumber)
                .index(0L).equals(code), "验证码错误，请重新输入！");
    }

    /**
     * 清除缓存
     *
     * @param phoneNumber
     * @param code
     * @param type
     */
    public void deleteVerifyCodeCache(String phoneNumber, String code, VerifyCodeType type) {
        Assert.notNull(type, "短信验证码类型不可为空");
        stringRedisTemplate.delete(type + phoneNumber);
        stringRedisTemplate.delete(VerifyCodeType.VERIFY_COUNT + phoneNumber);
    }

}
